package simplechat.server;

import simplechat.util.MessageUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @program: netty-study
 * @description: 服务处理类
 * @author: 胡海龙
 * @create: 2021-04-10 23:24:32
 **/
public class ChatServerHandle implements Runnable{

    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private volatile boolean stop;
    private Map<String,SocketChannel> currentUserList = new ConcurrentHashMap<>();

    public ChatServerHandle(Integer port) {
        try {
            selector = Selector.open();
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.bind(new InetSocketAddress(port),1024);
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("chat server is running ...");
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Override
    public void run() {
        while (!stop) {
            try {
                selector.select(1000);  //超时设置
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                SelectionKey key;
                while (iterator.hasNext()) {
                    key = iterator.next();
                    iterator.remove();
                    handleInput(key);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (selector != null) {
            try {
                selector.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void handleInput(SelectionKey key) throws IOException {
        try{
            if(key.isValid()){
                if(key.isAcceptable()){
                    System.out.println("新连接");
                    ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();
                    SocketChannel socketChannel = serverChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector,SelectionKey.OP_READ);
                }
                if(key.isReadable()){
                    SocketChannel socketChannel = (SocketChannel)key.channel();
                    readBuffer(socketChannel);
                }
            }
        } catch (IOException e){
            key.cancel();
            if(key.channel()!=null){
                key.channel().close();
            }
        }

    }

    private void readBuffer(SocketChannel channel) throws IOException {
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        int readBytes = channel.read(readBuffer);
        while(readBytes!=-1&&readBytes!=0){
            readBuffer.flip();
            while(readBuffer.hasRemaining()){
                byte[]bytes = new byte[readBuffer.remaining()];
                readBuffer.get(bytes);
                String receiveMessage = new String(bytes, StandardCharsets.UTF_8);
                String fromName = MessageUtil.getFromName(receiveMessage);
                String toName = MessageUtil.getToName(receiveMessage);
                System.out.println(toName);
                if("server".equals(toName)){
                    currentUserList.put(fromName,channel);  //保存该用户
                    System.out.println(currentUserList);
                    responseMessage(channel,"login success");
                }else{
                    if(currentUserList.containsKey(toName)){    //如果存在要发送的对象
                        System.out.println("用户存在");
                        SocketChannel toSocketChannel = currentUserList.get(toName);
                        responseMessage(toSocketChannel,receiveMessage);
                    }
                }
            }
            readBuffer.clear();
            readBytes = channel.read(readBuffer);
        }
    }

    private void responseMessage(SocketChannel channel, String response) throws IOException {
        if(response!=null&&!response.isEmpty()){
            byte[] bytes = response.getBytes();
            ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
            writeBuffer.put(bytes);
            writeBuffer.flip();
            channel.write(writeBuffer);
        }
    }
}
